<?php
/*
 * MCP 客户端实现（php-mcp SDK 版 - Swoole增强版）
 * https://wiki.swoole.com/zh-cn/#/
 * https://github.com/modelcontextprotocol/php-sdk
 * https://github.com/modelcontextprotocol/php-sdk.git
 * 基于协议：https://modelcontextprotocol.io/specification/2024-11-05
 */
namespace jy_agentmcp;
require_once ROOT_PLUGIN.'jy_agentmcp/class/sdk/autoload.php';
use Mcp\Server;
use Mcp\Server\Transport\SwooleWebSocketClientTransport;
use Swoole\Timer;
use RuntimeException;
defined('BY_JYA') or exit('error');
class jymcp extends \plugin{
    // 设备连接列表 (设备ID => 连接信息)
    private array $deviceConnections = [];
    // 设备配置列表 (从数据库读取)
    private array $devices = [];
    // 轮询间隔(秒)
    private int $pollingInterval = 10;
    // MCP服务器实例映射 (设备ID => Server)
    private array $servers = [];
    // 协程ID映射 (设备ID => 协程ID)
    private array $coroutineIds = [];
    public function __construct() {
        parent::__construct('jy_agentmcp');
        $this->logInfo("MCP客户端初始化开始");
        $this->loadDevicesFromDb();
        $this->logInfo("MCP客户端初始化完成");
    }

    /**
     * 从数据库加载设备列表
     */
    private function loadDevicesFromDb() {
        $this->logInfo("开始从数据库加载设备列表");
        // 从数据库查询所有MCP设备配置
        $devices = pdo_getall('jy_agentmcp_usergoods',['status' =>array(1,2),'mcpurl <>'=>''], ['deviceid', 'mcpurl', 'id', 'title'],'','id ASC');
        $devices=array(array('id'=>1,'title'=>'demo'));
        if (!empty($devices)) {
            foreach ($devices as $device) {
                $device['deviceid']=$device['deviceid']?:$device['id'];
                $this->devices[$device['deviceid']] = $device;
                $this->logInfo("加载设备 - ID: {$device['deviceid']}, 名称: {$device['title']}");
            }
        } else {
            $this->logWarning("数据库中未找到可用设备");
        }
    }

    /**
     * 启动多设备管理（单进程内）
     */
    public function startMultiDeviceManager() {
        $this->logInfo("尝试启动多设备管理");
        if (empty($this->devices)) {
            $this->logError("启动失败，没有可用设备");
            return $this->formatResult(false, '没有可用设备，请先在数据库配置设备');
        }

        if (!extension_loaded('swoole')) {
            throw new RuntimeException("未安装Swoole扩展");
        }

        // 启动主协程
        \Swoole\Coroutine\run(function () {
            $this->logInfo("多设备管理启动，共 " . count($this->devices) . " 个设备");
            // 为每个设备启动独立协程管理连接
            foreach ($this->devices as $deviceId => $device) {
                $this->logInfo("为设备 {$deviceId} 启动管理协程");
                $this->coroutineIds[$deviceId] = go(function () use ($deviceId, $device) {
                    $this->manageDeviceConnection($deviceId, $device);
                });
                $this->logInfo("设备 {$deviceId} 管理协程启动成功，协程ID: {$this->coroutineIds[$deviceId]}");
            }

            Timer::tick($this->pollingInterval * 1000, function () {
                $this->globalPollingCheck();
            });
        });

        return $this->formatResult(true, '多设备管理已启动');
    }

    /**
     * 管理单个设备的连接
     */
    private function manageDeviceConnection(string $deviceId, array $device) {
        $this->logInfo("开始管理设备连接 - 设备ID: {$deviceId}");
       //$mcpUrl = $device['mcpurl'];
        $mcpUrl = 'wss://api.xiaozhi.me/mcp/?token=eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjM5NTU5MSwiYWdlbnRJZCI6Njk5NjAxLCJlbmRwb2ludElkIjoiYWdlbnRfNjk5NjAxIiwicHVycG9zZSI6Im1jcC1lbmRwb2ludCIsImlhdCI6MTc1OTcxMzQ3OCwiZXhwIjoxNzkxMjcxMDc4fQ.jcdf47LCDpDJ_x5pIwZygHaMkcKqe2TdOlOIvCqvKDFgH-P1e8V-qzrZEf-51KyEMz9Ao8h0esyuWUw4wnNvdQ';
        // 初始化SDK服务器实例
        $this->initServer($deviceId,$mcpUrl);
        return '';
    }
    /**
     * 全局轮询检查
     */
    private function globalPollingCheck() {
        $this->logInfo("开始全局轮询检查");
        $onlineCount = 0;
        $totalCount = count($this->devices);
        
        // 检查所有设备状态
        foreach ($this->devices as $deviceId => $device) {
            if (!isset($this->deviceConnections[$deviceId])) {
                $this->logInfo("设备 {$deviceId} 无连接信息，视为离线");
                continue;
            }
            $status = $this->deviceConnections[$deviceId]['status'] ?? 0;
            $lastActive = $this->deviceConnections[$deviceId]['lastActive'] ?? 0;
            $lastActiveStr = $lastActive ? date('Y-m-d H:i:s', $lastActive) : '从未活动';
            if ($status == 1) {
                $onlineCount++;
                $this->logInfo("设备 {$deviceId} 在线，最后活动时间: {$lastActiveStr}");
            } else {
                $this->logInfo("设备 {$deviceId} 离线，最后活动时间: {$lastActiveStr}");
            }
        }
        
        $this->logInfo("全局轮询检查完成 - 在线设备: {$onlineCount}/{$totalCount}");
    }

    /**
     * 初始化SDK服务器（增强日志便于调试）
     */
    private function initServer(string $deviceId,$mcpUrl='') {
        $this->logInfo("构建MCP服务器实例 - 设备ID: {$deviceId}");
        // 使用 realpath 确保路径正确
        $targetDir = realpath(__DIR__ . '/sdk/mcp/sdk/src/Tools'); 
        $transport = new SwooleWebSocketClientTransport($mcpUrl);
        $server = Server::builder()
            ->setServerInfo('JY Agent MCP ('.$deviceId.')','1.0.0','单进程多设备MCP客户端')
            ->setDiscovery($targetDir)
            ->setPaginationLimit(50)
            ->build()
            ->connect($transport);
        $transport->listen();
        $this->servers[$deviceId] = $server;
        $this->deviceConnections[$deviceId] = [
            'status' => 1,
            'lastActive' => time(),
        ];
        return $server;
    }
    /**
     * 获取所有设备状态
     */
    public function getDevicesStatus(): array {
        $this->logInfo("获取所有设备状态");
        $status = [];
        foreach ($this->devices as $deviceId => $device) {
            $conn = $this->deviceConnections[$deviceId] ?? ['status' => 0, 'lastActive' => 0];
            $status[$deviceId] = [
                'name' => $device['title'] ?? $deviceId,
                'mcpurl' => $device['mcpurl'] ?? '',
                'status' => $conn['status'] ? '在线' : '离线',
                'lastActive' => $conn['lastActive'] ? date('Y-m-d H:i:s', $conn['lastActive']) : '从未连接'
            ];
            $this->logInfo("设备 {$deviceId} 状态: {$status[$deviceId]['status']}, 最后活动: {$status[$deviceId]['lastActive']}");
        }
        $this->logInfo("所有设备状态获取完成，共 " . count($status) . " 个设备");
        return $status;
    }

    /**
     * 格式化返回结果
     */
    private function formatResult(bool $success, string $message, array $data = []): array
    {
        $result = [
            'success' => $success,
            'message' => $message,
            'data' => $data
        ];
        $this->logInfo("格式化返回结果: " . json_encode($result, JSON_UNESCAPED_UNICODE));
        return $result;
    }

    /**
     * 日志记录
     */
    public function logInfo(string $message): void
    {
        $this->log("[INFO] {$message}");
    }

    private function logWarning(string $message): void {
        $this->log("[WARNING] {$message}");
    }

    private function logError(string $message): void {
        $this->log("[ERROR] {$message}");
    }

    private function log(string $message): void
    {
        $logFile = ROOT_D . '/addons/jy_agentmcp/mcp_' . date('Ymd') . '.log';
        $dir = dirname($logFile);
        if (!is_dir($dir)) {
            mkdir($dir, 0755, true);
        }
        $content = date('Y-m-d H:i:s') . " {$message}\n";
        file_put_contents($logFile, $content, FILE_APPEND);
    }
}
?>